/* exported mc_block_line */

/* global $ */
/* global mc_util_is_object_dom */
/* global mc_random_color */
/* global mc_util_is_object */
/* global mc_util_is_array */


/************************************************************************************************
 * 类型:
 *    构造函数
 * 功能:
 *    构造线条
 * 参数:
 *    @param { Promise<String> } id 容器id
 * 返回:
 *    @returns { Promise<String> } 参数1
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2021-09-10
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_block_line(id) {
    var obj_container = document.getElementById(id);

    if (!obj_container) {
        return false;
    }

    // ******************** define ******************** //
    // 连线队列
    var obj_queue = { };
    // obj_queue 数据格式
    // key: {
    //     queue: [dom数据],
    //     color: 队列当前颜色值,
    //     parent: 连线容器dom对象
    // }
    var b_start_end_mark = true;
    var arr_color = [];
    var g_ui_color_idx = 0;

    // ******************** save node ******************** //
    var obj_node_marker = mc_construct_marker("init_def", "green");
    var obj_node_g = document.createElementNS("http://www.w3.org/2000/svg", "g");

    // init layer
    var str_line_layer = "<svg id='mc_svg_layer_line' width=" + obj_container.offsetWidth + " height=" + obj_container.offsetHeight + " version='1.1' xmlns='http://www.w3.org/2000/svg'></svg>";

    $(obj_container).children("#mc_svg_layer_line").remove();
    $(obj_container).append(str_line_layer);

    // save line svg obj
    var m_obj_svg_line = document.getElementById("mc_svg_layer_line");

    // 设置线条扩展参数; [x轴偏移值, y轴偏移值]
    var obj_line_param = {
        // 前一块偏移值对象
        pre: [0,0],
        // 后一块
        next: [0,0]
    };


    // ********************************************************************* fn ********************************************************************* //
    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    初始化两端标识
     * 参数:
     *    @param { Promise<String> } ui_type === 0(开始块);
     *    @param { Promise<String> } key 块key值
     *    @param { Promise<Object> } obj_pos 块位置值
     * 返回:
     *    @returns { Promise<String> } 参数1
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-09-10
     *       内容 : 所有代码
     ************************************************************************************************/
    function init_start_end_marks(ui_type, key, obj_pos) {
        if ("undefined" === typeof ui_type || "undefined" === typeof key || "object" !== typeof obj_pos) {
            return false;
        }

        // exist
        var str_class = (ui_type ? "mark_end" : "mark_start");
        var str_id_circle = str_class + "_" + key;
        var str_id_text = str_id_circle + "_" + "text";
        var obj_exist_circle = m_obj_svg_line.getElementById(str_id_circle);

        if (obj_exist_circle) {
            obj_exist_circle.setAttribute("cx", obj_pos.left);
            obj_exist_circle.setAttribute("cy", obj_pos.top);
            var obj_exist_text = m_obj_svg_line.getElementById(str_id_text);

            obj_exist_text.setAttribute("x", obj_pos.left);
            obj_exist_text.setAttribute("y", obj_pos.top);
            return true;
        }

        // circle
        var obj_circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");

        obj_circle.setAttribute("id", str_id_circle);
        obj_circle.setAttribute("class", str_class);
        obj_circle.setAttribute("cx", obj_pos.left);
        obj_circle.setAttribute("cy", obj_pos.top);
        obj_circle.setAttribute("r", "15");
        obj_circle.setAttribute("stroke-width", "2");
        obj_circle.setAttribute("fill", (ui_type ? "red" : "green"));

        // text
        var obj_text = document.createElementNS("http://www.w3.org/2000/svg", "text");

        obj_text.setAttribute("id", str_id_text);
        obj_text.setAttribute("class", "text_svg");
        obj_text.setAttribute("x", obj_pos.left);
        obj_text.setAttribute("y", obj_pos.top);
        obj_text.setAttribute("fill", "#fff");
        obj_text.setAttribute("alignment-baseline", "middle");
        obj_text.setAttribute("text-anchor", "middle");
        obj_text.innerHTML = ((ui_type ? "E" : "S") + key);

        // inser dom
        // circle and text container
        var obj_mark_wrap = obj_node_g.cloneNode(false);

        obj_mark_wrap.setAttribute("line_mark", key);
        obj_mark_wrap.appendChild(obj_circle);
        obj_mark_wrap.appendChild(obj_text);
        m_obj_svg_line.appendChild(obj_mark_wrap);
        return true;
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    构造线条id;
     * 参数:
     *    @param { Promise<Object> } obj_start 开始块对象; 带id属性;
     *    @param { Promise<Object> } obj_end 结束块对象; 带id属性
     * 返回:
     *    @returns { Promise<String> } 连线id || false
     * 例子:
     *    NA
     * 备注:
     *    以上参数对象并不一定为dom对象; 只要时带id属性值对象即可,并且id值为字符串；
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-02-04
     *       内容 : 所有代码
     ************************************************************************************************/
    function mc_constrct_line_id(obj_start, obj_end) {
        if (obj_start && obj_end) {
            if ("string" === typeof obj_start.id && "string" === typeof obj_end.id && obj_start.id.trim() && obj_end.id.trim()) {
                return obj_start.id.trim() + "_" + obj_end.id.trim();
            }
        }
        return false;
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    创建线条dom对象
     * 参数:
     *    @param { Promise<String> } str_line_id 线条id
     *    @param { Promise<Number> } x1 开始点x坐标
     *    @param { Promise<Number> } y1 开始点y坐标
     *    @param { Promise<Number> } x2 结束点x坐标
     *    @param { Promise<Number> } y2 结束点y坐标
     *    @param { Promise<String> } str_class 添加的线条类
    //  *    @param { Promise<String> } key 线条key值
     * 返回:
     *    @returns { Promise<Object> } {} 返回线条和箭头的dom对象  { svg_line: 线条对象; svg_marker: 箭头对象 }
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2020-11-25
     *       内容 : 所有代码
     ************************************************************************************************/
    function mc_construct_line(str_line_id, x1, y1, x2, y2, str_class) {
        if (!str_line_id) {
            return false;
        }

        var str_marker_id = "arrow_marker_" + str_line_id;
        // line
        var obj_svg_line = document.createElementNS("http://www.w3.org/2000/svg", "line");
        var str_def_class = "line";

        if ("string" === typeof str_class && str_class.trim()) {
            str_def_class += str_class;
        }

        obj_svg_line.setAttribute("id", str_line_id);
        obj_svg_line.setAttribute("class", str_def_class);
        obj_svg_line.setAttribute("x1", x1);
        obj_svg_line.setAttribute("y1", y1);
        obj_svg_line.setAttribute("x2", x2);
        obj_svg_line.setAttribute("y2", y2);
        // obj_svg_line.setAttribute("stroke", line_color);
        obj_svg_line.setAttribute("stroke-width", "2");
        obj_svg_line.setAttribute("marker-end", "url(#" + str_marker_id + ")");

        // marker
        // use clone node
        var obj_marker_res = obj_node_marker.cloneNode(true);

        obj_marker_res.setAttribute("id", str_marker_id );
        // obj_marker_res.setAttribute("style", "fill:" + line_color + "");

        // line and marker container
        var obj_line_wrap = obj_node_g.cloneNode(false);

        obj_line_wrap.appendChild(obj_marker_res);
        obj_line_wrap.appendChild(obj_svg_line);

        return obj_line_wrap;
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    创建箭头dom对象
     * 参数:
     *    @param { Promise<String> } str_marker_id 箭头id
    //  *    @param { Promise<String> } marker_col 箭头颜色; 默认与线条颜色一致
     * 返回:
     *    @returns { Promise<Object> } 生成的箭头dom对象
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2020-11-25
     *       内容 : 所有代码
     ************************************************************************************************/
    function mc_construct_marker(str_marker_id ) {
        if ("string" !== typeof str_marker_id) {
            return {};
        }

        var obj_svg_marker = document.createElementNS("http://www.w3.org/2000/svg", "marker");

        obj_svg_marker.setAttribute("id", str_marker_id);
        // obj_svg_marker.setAttribute("stroke-width", "2");

        obj_svg_marker.setAttribute("orient", "auto");
        obj_svg_marker.setAttribute("markerUnits", "strokeWidth");

        obj_svg_marker.setAttribute("markerWidth", "10");
        obj_svg_marker.setAttribute("markerHeight", "10");

        obj_svg_marker.setAttribute("refX", "8");
        obj_svg_marker.setAttribute("refY", "4");

        var obj_marker_path = document.createElementNS("http://www.w3.org/2000/svg", "path");
        var path_d = "M0,1 L0,7 L8,4 z";

        obj_marker_path.setAttribute("d", path_d);
        // obj_marker_path.setAttribute("style", "fill:" + marker_col + "");

        obj_svg_marker.appendChild(obj_marker_path);

        return obj_svg_marker;
    }


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    创建线条
     * 参数:
     *    @param { Promise<String> } key 线条key
     *    @param { Promise<Object> } arr_dom 元素dom对象; 当前队列最后一个元素
     * 返回:
     *    NA
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-09-10
     *       内容 : 所有代码
     ************************************************************************************************/
    function create_line(key, arr_dom) {
        if ("object" !== typeof arr_dom) {
            return;
        }

        var ui_len = arr_dom.length;
        var obj_dom = arr_dom[ui_len - 1];

        // save line value
        obj_dom.LINE_KEY = key;
        obj_dom.LINE_IDX = ui_len;

        if (b_start_end_mark && 1 === ui_len) {
            init_start_end_marks(0, key, get_div_data(obj_dom, obj_line_param.pre));
        }
        if (2 > ui_len) {
            return;
        }

        var div_next = get_div_data(obj_dom, obj_line_param.next);

        create_one_line(get_div_data(arr_dom[ui_len - 2], obj_line_param.pre), div_next, key);

        if (b_start_end_mark) {
            init_start_end_marks(1, key, div_next);
        }
    }


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    获取dom对象的数据; 默认获取中心点(两个块之间连线无间隙);
     * 参数:
     *    @param { Promise<Object> } obj_div div dom对象;
     *    @param { Promise<Array> } arr_xy xy轴偏移值; [x轴,y轴]; 数据包含符号eg:[-30, +30]
     * 返回:
     *    @returns { Promise<Object> } 该对象的id,中心点top,left值
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2020-1-8
     *       内容 : 所有代码
     *    2. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2020-11-27
     *       内容 : 获取的位置值为读取样式值(优化性能)
     ************************************************************************************************/
    function get_div_data(obj_div, arr_xy) {
        if (!mc_util_is_object_dom(obj_div)) {
            return false;
        }
        arr_xy = arr_xy || [0,0];

        var box_width = Number((obj_div.style.width).split("px")[0]);
        var box_height = Number((obj_div.style.height).split("px")[0]);
        var box_top = Number((obj_div.style.top).split("px")[0]);
        var box_left = Number((obj_div.style.left).split("px")[0]);

        return {
            id: obj_div.id,
            top: (box_height / 2) + box_top + (arr_xy[1]),
            left: (box_width / 2) + box_left + (arr_xy[0])
        };
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    循环两两模组连线
     * 参数:
     *    @param { Promise<Object> } obj_start 开始块连接点数据对象
     *    @param { Promise<Object> } obj_end 结束块连接点数据对象
     *    @param { Promise<Object> } key 当前队列key
     * 返回:
     *    @returns { Promise<Boolean> } false === 参数错误
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-01-19
     *       内容 : 所有代码
     ************************************************************************************************/
    function create_one_line(obj_start, obj_end, key) {
        if (!mc_util_is_object(obj_start) || !mc_util_is_object(obj_end)) {
            return false;
        }

        // var line_id = obj_start.id + "_" + obj_end.id;
        var line_id = mc_constrct_line_id(obj_start, obj_end);

        if (!line_id) {
            return false;
        }

        var obj_edit_line = document.getElementById(line_id) || document.getElementById(obj_end.id + "_" + obj_start.id);

        if (obj_edit_line) {
            obj_edit_line.setAttribute("x1", obj_start.left);
            obj_edit_line.setAttribute("y1", obj_start.top);
            obj_edit_line.setAttribute("x2", obj_end.left);
            obj_edit_line.setAttribute("y2", obj_end.top);
            return true;
        }

        // judge show or hide mod line  1 === show || 0 === hide
        var str_mod_line_wrap_div_class = "";
        var obj_line_res = mc_construct_line(line_id, obj_start.left, obj_start.top, obj_end.left, obj_end.top, str_mod_line_wrap_div_class, key);

        if (obj_line_res) {
            if (b_start_end_mark) {
                obj_queue[key].parent.insertBefore(obj_line_res, obj_queue[key].parent.firstChild);
            } else {
                obj_queue[key].parent.appendChild(obj_line_res);
            }
        }

        return true;
    }


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    key值一组元素连线
     * 参数:
     *    @param { Promise<String> } key 队列key值
     *    @param { Promise<String> } arr_queue 该key值队列dom数组
     * 返回:
     *    NA
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-01-19
     *       内容 : 所有代码
     ************************************************************************************************/
    function connect_group(key, arr_queue) {
        if ("string" !== typeof key || !mc_util_is_array(arr_queue)) {
            return;
        }

        key = key.trim();

        var arr_dom = arr_queue;
        var ui_dom_len = arr_dom.length;

        // delete cur queue old line
        delete_line(key);

        if (0 === ui_dom_len) {
            return;
        }

        // just one
        if (1 === ui_dom_len) {
            var obj_item = arr_dom[0];

            // save line data
            obj_item.LINE_IDX = 1;
            obj_item.LINE_KEY = key;
            if (b_start_end_mark) {
                init_start_end_marks(0, key, get_div_data(obj_item, obj_line_param.pre));
            }
            return;
        }


        // multiple
        for (var line_idx = 0; line_idx < ui_dom_len; line_idx++) {
            var item = arr_dom[line_idx];

            if (item) {
                var ui_idx = Number(line_idx + 1);

                // save line data
                item.LINE_IDX = ui_idx;
                item.LINE_KEY = key;

                var strat_div = get_div_data(item, obj_line_param.pre);

                // line
                if (line_idx !== ui_dom_len - 1) {
                    create_one_line(strat_div, get_div_data(arr_dom[line_idx + 1], obj_line_param.next), key);
                }

                if (b_start_end_mark) {
                    if (0 === line_idx) {
                        init_start_end_marks(0, key, strat_div);
                    }
                    if (line_idx === ui_dom_len - 1) {
                        init_start_end_marks(1, key, get_div_data(item, obj_line_param.next));
                    }
                }
            }
        }
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    删除线条; 并且删除两端标识
     * 参数:
     *    @param { Promise<String> } key 连线key值
     * 返回:
     *    @returns { Promise<String> } 参数1
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-09-13
     *       内容 : 所有代码
    ************************************************************************************************/
    function delete_line(key) {
        if ("string" !== typeof key) {
            return false;
        }

        // line
        var obj_line = m_obj_svg_line.querySelectorAll("[line_g='" + key + "']");
        var i = 0;
        var len = obj_line.length;

        while (i < len) {
            obj_line[i].innerHTML = "";
            // obj_line[i].parentNode.removeChild(obj_line[i]);
            i++;
        }

        // mark
        var obj_mark = m_obj_svg_line.querySelectorAll("[line_mark='" + key + "']");

        len = obj_mark.length;
        i = 0;
        while (i < len) {
            obj_mark[i].parentNode.removeChild(obj_mark[i]);
            i++;
        }

        return true;
    }


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    创建当前相同key的线条容器; "line_g"标识
     * 参数:
     *    @param { Promise<String> } key 队列key值
     *    @param { Promise<String> } color 一组key颜色
     *    @param { Promise<String> } 参数1
     * 返回:
     *    @returns { Promise<String> } 参数1
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-09-15
     *       内容 : 所有代码
    ************************************************************************************************/
    function create_line_g_container(key, color) {
        if ("undefined" === typeof key) {
            return false;
        }

        color = color || "green";
        var obj_line_g = m_obj_svg_line.querySelectorAll("[line_g='" + key + "']");

        if (!(obj_line_g.length)) {
            var obj_svg_line_g = obj_node_g.cloneNode();

            obj_svg_line_g.setAttribute("stroke", color);
            obj_svg_line_g.setAttribute("fill", color);
            obj_svg_line_g.setAttribute("line_g", key);
            // obj_svg_line_g.setAttribute("g_line_key", key);
            m_obj_svg_line.appendChild(obj_svg_line_g);
            return obj_svg_line_g;
        }

        return obj_line_g[0];
    }


    // ********************************************************************* 接口 ********************************************************************* //
    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置队列; 该接口设置dom接在设置的key值队列最后一个;
     * 参数:
     *    @param { Promise<String> } key 队列key
     *    @param { Promise<Object> } dom 当前队列最后一个对象
     *    @param { Promise<Boolean> } connect 当前块是否连线
     * 返回:
     *    @returns { Promise<Boolean> } false === 参数错误
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-09-10
     *       内容 : 所有代码
     ************************************************************************************************/
    this.set_queue = function (key, dom, connect) {
        if ("string" !== typeof key || !mc_util_is_object_dom(dom)) {
            return false;
        }

        if (!key.trim()) {
            return false;
        }

        if (!obj_queue[key]) {
            obj_queue[key] = {
                color: arr_color[g_ui_color_idx],
                queue: [dom],
                parent: create_line_g_container(key, arr_color[g_ui_color_idx])
            };
            g_ui_color_idx++;
        } else {
            obj_queue[key].queue.push(dom);
        }

        if (connect) {
            create_line(key, obj_queue[key].queue);
        }
        return true;
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    是否需要头尾标记; 默认头尾标记为 -> "S"(开始) ||"E"(结束) + 当前队列key;
     * 参数:
     *    @param { Promise<Boolean> } b === true 需要
     * 返回:
     *    @returns { Promise<Boolean> } false === 参数错误
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-09-10
     *       内容 : 所有代码
     ************************************************************************************************/
    this.has_mark = function (b) {
        if ("boolean" !== typeof b) {
            return false;
        }

        b_start_end_mark = b;
        return true;
    };


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置颜色数量
     * 参数:
     *    @param { Promise<Number> } num 线条数量总数
     * 返回:
     *    @returns { Promise<Boolean> } false === 参数错误
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-09-10
     *       内容 : 所有代码
     ************************************************************************************************/
    this.set_color_num = function (num) {
        if ("number" !== typeof num || arr_color.length === num) {
            return false;
        }

        for (var idx = 0; idx <= num; idx++) {
            arr_color[idx] = mc_random_color();
        }

        return true;
    };


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *     获取当前队列下标; 最后一个元素的下标; 该队列下标从1开始
     * 参数:
     *    @param { Promise<String> } key 队列key
     * 返回:
     *    @returns { Promise<Boolean> } false === 参数错误
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-09-10
     *       内容 : 所有代码
     ************************************************************************************************/
    this.get_idx = function (key) {
        if (obj_queue[key]) {
            return obj_queue[key].queue.length + 1;
        }

        return 1;
    };


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *     获取当前块 key值
     * 参数:
     *    @param { Promise<Object> } obj_dom 连线的dom
     * 返回:
     *    @returns { Promise<String> } 该dom在队列的key值
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-09-14
     *       内容 : 所有代码
    ************************************************************************************************/
    this.get_key = function (obj_dom) {
        return obj_dom.LINE_KEY;
    };


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *     修改队列内元素key值
     * 参数:
     *    @param { Promise<String> } key === 新值
     *    @param { Promise<Object> } dom 修改的dom元素
     *    @param { Promise<Object> } connect 是否更新当前修改的旧key和新key队列连接
     * 返回:
     *    @returns { Promise<String> } 参数1
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-09-13
     *       内容 : 所有代码
    ************************************************************************************************/
    this.modify_key = function (key, dom, connect) {
        if ("string" !== typeof key || !mc_util_is_object_dom(dom) || "undefined" === typeof dom.LINE_KEY || dom.LINE_KEY === key) {
            return false;
        }

        // delete origin key
        var str_origin_key = dom.LINE_KEY;
        var arr_queue = obj_queue[dom.LINE_KEY] ? obj_queue[dom.LINE_KEY].queue : false;

        if (!arr_queue || !arr_queue.length) {
            return false;
        }

        var ui_idx = dom.LINE_IDX - 1;

        if (arr_queue[ui_idx] !== dom) {
            return false;
        }

        // delete arr_queue[ui_idx];
        arr_queue.splice(ui_idx, 1);

        if ("function" !== typeof this.callback_update_dom) {
            return false;
        }

        // 更新旧队列值
        var ui_len = arr_queue.length;

        for (var idx = ui_idx; idx < ui_len; idx++) {
            var item_dom = arr_queue[idx];

            item_dom.LINE_IDX = idx + 1;
            this.callback_update_dom(item_dom, null, Number(item_dom.LINE_IDX));
        }

        // set new index; 必须先获取
        var ui_dome_idx = this.get_idx(key);

        // 设置新队列key && ui回调
        if (this.set_queue(key, dom, true)) {
            this.callback_update_dom(dom, null, ui_dome_idx);
        }

        // 更新line(旧key和新key)
        if (connect) {
            this.update_line(str_origin_key);
            this.update_line(key);
        }
        return true;
    };


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    更新连线
     * 参数:
     *    @param { Promise<String> } key 更新的连线key (为空时更新所有连线)
     * 返回:
     *    @returns { Promise<Boolean> }
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-09-13
     *       内容 : 所有代码
    ************************************************************************************************/
    this.update_line = function (key) {
        if ("string" === typeof key && key.trim()) {
            if (obj_queue[key].queue) {
                connect_group(key, obj_queue[key].queue);
                return true;
            }
            return false;
        }

        for (var str_key in obj_queue) {
            if (Object.hasOwnProperty.call(obj_queue, str_key)) {
                connect_group(str_key, obj_queue[str_key].queue);
            }
        }
        return true;
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    清空数据; 初始化数据: 队列，颜色值，颜色值下标，线条头尾标识, 线条偏移;
     * 参数:
     *    NA
     * 返回:
     *    NA
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-12-15
     *       内容 : 所有代码
    ************************************************************************************************/
    this.clear = function () {
        obj_queue = { };
        b_start_end_mark = true;
        arr_color = [];
        g_ui_color_idx = 0;
        obj_line_param = {
            pre: [0,0],
            next: [0,0]
        };
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置线条端点偏移; 两点之间连线无间隙; 若需要设置间隙(即两个块之间相对于中心点偏移设置)，可以使用该接口;
     * 参数:
     *    @param { Promise<Object> } obj_param 线条扩展参数; {pre:[x轴偏移值, y轴偏移值], next:[...]}; eg:[-30,+30]
     * 返回:
     *    @returns { Promise<String> } 参数1
     * 例子:
     *    NA
     * 备注:
     *    一条线点有两组数据, pre:前一块的点偏移(相对与中心点); next=后一块
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-12-16
     *       内容 : 所有代码
    ************************************************************************************************/
    this.set_line_point_offst = function (obj_param) {
        if (!mc_util_is_object(obj_param)) {
            return false;
        }

        // previous
        if (mc_util_is_array(obj_param.pre)) {
            var ui_x = obj_param.pre[0];
            var ui_y = obj_param.pre[1];

            if ("number" === typeof ui_x && !isNaN(ui_x)) {
                obj_line_param.pre[0] = ui_x;
            }
            if ("number" === typeof ui_y && !isNaN(ui_y)) {
                obj_line_param.pre[1] = ui_y;
            }
        }

        // next
        if (mc_util_is_array(obj_param.next)) {
            var ui_x_n = obj_param.next[0];
            var ui_y_n = obj_param.next[1];

            if ("number" === typeof ui_x_n && !isNaN(ui_x_n)) {
                obj_line_param.next[0] = ui_x_n;
            }
            if ("number" === typeof ui_y_n && !isNaN(ui_y_n)) {
                obj_line_param.next[1] = ui_y_n;
            }
        }
        return true;
    };

    // 回调更新
    // @pamra dom 更新的当前dom
    // @pamra dom 更新的dom key值(队列key)
    // @pamra dom 更新的dom index值(序号)
    this.callback_update_dom = function (dom, key, idx) {}; /* eslint-disable-line */
    return true;
}
